package com.heima.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.search.pojos.ApAssociateWords;
import com.heima.search.service.SearchService;
import lombok.SneakyThrows;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Service
public class SearchServiceImpl implements SearchService {

  @Autowired
  private RestHighLevelClient client;



  /**
   * 基本搜索业务
   *
   * @param dto
   * @return
   */

  @Override
  public ResponseResult search(UserSearchDto dto) throws IOException {
    //TODO
    //检查参数
    if (dto == null || StringUtils.isNotBlank(dto.getSearchWords())) {
      return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }
    //设置查询条件
    SearchRequest searchRequest = new SearchRequest("app_info_article");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    //布尔查询
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    //对关键字进行分词之后查询
    QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(dto.getSearchWords()).field("title").field("content").defaultOperator(Operator.OR);
    // QueryBuilders.queryStringQuery(dto.getSearchWords().)
    boolQueryBuilder.filter(queryStringQueryBuilder);
    //查询小于mindate的数据
    RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime").lt(dto.getMinBehotTime().getTime());
    boolQueryBuilder.filter(rangeQueryBuilder);
    //分页查询
    searchSourceBuilder.from(0);
    searchSourceBuilder.size(dto.getPageSize());
    //按照发布时间到序查询
    searchSourceBuilder.sort("publishTime", SortOrder.DESC);
    //设置高亮
    HighlightBuilder highlightBuilder = new HighlightBuilder();
    highlightBuilder.field("title");
    highlightBuilder.preTags("<font style='color: red;font-size:inherit'>");
    highlightBuilder.preTags("</font>");
    searchSourceBuilder.highlighter(highlightBuilder);
    searchSourceBuilder.query(boolQueryBuilder);
    searchRequest.source(searchSourceBuilder);
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
    List<Map> list = new ArrayList<>();
    SearchHit[] hits = searchResponse.getHits().getHits();
    for (SearchHit hit : hits) {
      String json = hit.getSourceAsString();
      Map map = JSON.parseObject(json, Map.class);
      //处理高亮
      if (hit.getHighlightFields() != null && hit.getHighlightFields().size() > 0) {
        Text[] titles = hit.getHighlightFields().get("title").getFragments();
        String title = StringUtils.join(titles);
        //高亮标题
        map.put("h_title", title);
      } else {
        //原始标题
        map.put("h_title", map.get("title"));
      }
      list.add(map);
    }
    return ResponseResult.okResult(list);
  }

  /**
   * 自动补全功能
   *
   * @param dto
   * @return
   */
  @Autowired
  private MongoTemplate mongoTemplate;
  @Override
  public ResponseResult load(UserSearchDto dto) {
    //TODO
   //参数检查
    if (dto==null||StringUtils.isBlank(dto.getSearchWords())){
      return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }
    //分页检查
    if (dto.getPageSize()>20){
      dto.setPageSize(20);
    }
    //执行查询 模糊查询
    Query associatewords = Query.query(Criteria.where("associatewords").regex(".*?\\" + dto.getSearchWords() + ".*"));
        associatewords.limit(dto.getPageSize());
    List<ApAssociateWords> wordsList = mongoTemplate.find(associatewords, ApAssociateWords.class);
    return ResponseResult.okResult(wordsList);
  }
}
